<template>
  <div class="chat-container">
    <div class="message-list" ref="messageList">
      <div 
        v-for="(message, index) in messages" 
        :key="index" 
        :class="['message-item', message.isUser ? 'user-message' : 'assistant-message', 'animate-fade-in']"
        :style="{ animationDelay: `${index * 0.05}s` }"
      >
        <div class="avatar">
          <img :src="message.isUser ? userAvatar : assistantAvatar" alt="avatar" class="avatar-img"/>
        </div>
        <div class="message-content">
          <template v-if="message.isLoading">
            <div class="loading-container">
              <LoadingDots class="loading-indicator" />
              <p class="loading-tip">这会查询你所有的文件资料，时间可能要1-2分钟，请耐心等待~</p>
            </div>
          </template>
          <div v-else class="message-text" v-html="message.content"></div>
        </div>
      </div>
    </div>
    
    <div class="input-area animate-fade-in" style="animation-delay: 0.3s">
      <div class="input-wrapper">
        <textarea 
          v-model="inputMessage" 
          @keyup.enter="sendMessage"
          rows="1"
          class="message-input"
          :class="{ 'input-focused': inputFocused, 'input-disabled': isLoading }"
          @focus="inputFocused = true"
          @blur="inputFocused = false"
          :disabled="isLoading"
          :placeholder="isLoading ? '正在查询文件资料，请勿重复提交...' : '发消息，请输入...'"
        ></textarea>
        <div 
          class="send-button" 
          @click="sendMessage" 
          :class="{ 'active': inputMessage.trim(), 'disabled': isLoading || !inputMessage.trim() }"
          :title="isLoading ? '正在查询中...' : (inputMessage.trim() ? '发送消息' : '请输入查询内容')"
        >
          <template v-if="isLoading">
            <div class="send-loading">
              <svg t="1710400669747" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" width="18" height="18">
                <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z" fill="currentColor"/>
                <path d="M13 7h-2v6h6v-2z" fill="currentColor">
                  <animateTransform attributeName="transform" type="rotate" from="0 12 12" to="360 12 12" dur="1s" repeatCount="indefinite"/>
                </path>
              </svg>
            </div>
          </template>
          <template v-else>
            <svg t="1710400669747" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4231" width="24" height="24">
              <path d="M931.4 481.3L815.9 396l0.3-0.4-604.7-249c-3.8-1.6-7.9-1.9-11.9-1l-0.3-0.7L135 171.3c-12.3 2.7-20.3 14.8-17.6 27.1 0.9 4.3 3.1 8 6.2 10.9l-0.3 0.7 155.6 130.3L492.3 436l-213.4 95.7-140.9 118c-9.7 8.1-11 22.6-2.8 32.3 3.9 4.6 9.3 7.5 15.2 8.1l0.3 0.7 63.9 26.3c4 1.6 8.1 1.9 12.1 1l0.3 0.7 201.4-83 139.3 57.4c4 1.6 8.1 1.9 12.1 0.9l0.3 0.7 63.9-26.3c12.3-2.7 20.3-14.8 17.6-27.1-0.9-4.3-3.1-8-6.2-10.9l0.3-0.7-102.8-86 389.4-174.6c11.3-5.1 16.3-18.3 11.3-29.6-2.3-4.9-6-8.6-10.8-11z" p-id="4232"></path>
            </svg>
          </template>
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts">
import { useLoginUserStore } from "@/store/user";
import { defineComponent, ref, nextTick } from 'vue'
import LoadingDots from '@/components/common/LoadingDots.vue'
import { getApiUrl, API_PATHS } from '@/config/api'
import { ElMessage } from 'element-plus'
import { downloadUrlParam } from '@/api/file'
import JSONBIG from 'json-bigint'

const jsonParser = JSONBIG({ storeAsString: true })

function parseJSON(str: string) {
  const bigIntRegex = /([^"]:)(\d{16,})([\D])/g;
  const wrappedStr = str.replace(bigIntRegex, '$1"$2"$3');
  return JSON.parse(wrappedStr);
}

const customJSONParse = (text: string) => {
  return JSON.parse(text, (key, value) => {
    if (typeof value === 'number' && Number.isInteger(value) && Math.abs(value) > Number.MAX_SAFE_INTEGER) {
      return value.toString();
    }
    return value;
  });
};

declare global {
  interface Window {
    handleFileDownload: (fileId: string, fileName: string, isFolder: boolean) => Promise<void>;
  }
}

interface FileItem {
  id: string; file_id: string | null; file_name: string; file_type: string | null;
  file_suffix: string | null; file_size: number | null; gmt_create: string; gmt_modified: string;
}

interface StorageInfo { used_size: number; total_size: number; used_percentage: number; }
interface FileStatistics { total_files: number; file_types: { [key: string]: number; }; }

export default defineComponent({
  name: 'Answer',
  components: { LoadingDots },
  setup() {
    const messages = ref<Array<{isUser: boolean; content: string; isLoading?: boolean}>>([
      { isUser: false, content: '我是文件查询助手，请输入查询条件。' }
    ]);
    const inputMessage = ref('');
    const messageList = ref<HTMLElement | null>(null);
    const userAvatar = require('@/assets/user-avatar.png');
    const assistantAvatar = require('@/assets/assistant-avatar.png');
    const isLoading = ref(false);
    const inputFocused = ref(false);
    const account_no = ref(localStorage.getItem('accountNo'));

    const scrollToBottom = () => {
      nextTick(() => {
        if (messageList.value) messageList.value.scrollTop = messageList.value.scrollHeight;
      });
    };

    const formatFileSize = (size: number) => {
      if (!size) return '-';
      const units = ['B', 'KB', 'MB', 'GB', 'TB'];
      let index = 0, fileSize = size;
      while (fileSize >= 1024 && index < units.length - 1) {
        fileSize /= 1024; index++;
      }
      return `${fileSize.toFixed(2)} ${units[index]}`;
    };

    const getFileIcon = (fileType: string) => {
      switch (fileType?.toUpperCase()) {
        case 'IMG': return '🖼️';
        case 'DOC': case 'DOCX': return '📄';
        case 'PDF': return '📑';
        case 'VIDEO': return '🎥';
        case 'AUDIO': return '🎵';
        case '文件夹': return '📁';
        default: return '📄';
      }
    };

    const sendMessage = async () => {
      const trimmedMsg = inputMessage.value.trim();
      if (!trimmedMsg || isLoading.value) return;

      messages.value.push({ isUser: true, content: trimmedMsg });
      messages.value.push({ isUser: false, content: '', isLoading: true });
      inputMessage.value = '';
      isLoading.value = true;
      scrollToBottom();

      try {
        const token = localStorage.getItem('token_ai_pan') || '';
        const response = await fetch(getApiUrl(API_PATHS.PAN_QUERY), {
          method: 'POST',
          headers: { 'Content-Type': 'application/json', 'token': token },
          body: JSON.stringify({ account_no: account_no.value, query: trimmedMsg })
        });

        if (!response.ok) throw new Error(`请求失败: ${response.status}（${response.statusText}）`);
        
        const text = await response.text();
        const responseData = jsonParser.parse(text);
        let formattedContent = '';

        if (responseData.code === 0) {
          if (responseData.data && responseData.data.type === 'storage_info') {
            const storageData = responseData.data.data;
            if (storageData) {
              const storageInfo = {
                used_size: Number(storageData.used_size) || 0,
                total_size: Number(storageData.total_size) || 10485760,
                used_percentage: Number(storageData.used_percentage) || 0
              };
              const usedSize = formatFileSize(storageInfo.used_size);
              const totalSize = formatFileSize(storageInfo.total_size);
              const percentage = storageInfo.used_percentage.toFixed(2);
              
              formattedContent = `
                <div class="storage-info animate-fade-in-up">
                  <div class="storage-header"><span class="storage-title">存储空间使用情况</span><span class="storage-percentage">${percentage}%</span></div>
                  <div class="storage-progress"><div class="progress-bar" style="width: ${percentage}%"></div></div>
                  <div class="storage-details">
                    <div class="storage-used"><span class="label">已使用</span><span class="value">${usedSize}</span></div>
                    <div class="storage-total"><span class="label">总容量</span><span class="value">${totalSize}</span></div>
                  </div>
                </div>
              `;
            } else formattedContent = '未获取到有效的存储空间数据';
          } 
          else if (responseData.data && responseData.data.type === 'text') {
            formattedContent = responseData.data.content || '查询到以下文本信息：无具体内容';
          } 
          else if (responseData.data && responseData.data.type === 'file_list') {
            const fileList = responseData.data.data as FileItem[];
            formattedContent = '<div class="file-list animate-fade-in-up">\n';
            if (fileList.length === 0) {
              formattedContent += '<div class="empty-file-list">未查询到匹配的文件</div>';
            } else {
              fileList.forEach(file => {
                const isFolder = file.file_size === null;
                const fileType = file.file_type || (isFolder ? '文件夹' : '文件');
                const fileName = file.file_name;
                const fileId = String(file.id);
                // 转义单引号防止HTML语法错误
                const escapedFileName = fileName.replace(/'/g, '\\\'');
                
                formattedContent += `
                  <div class="file-item">
                    <span class="file-icon">${getFileIcon(fileType)}&nbsp&nbsp</span>
                    ${isFolder ? 
                      `<span class="file-name">${fileName}</span>` :
                      `<span class="file-name" style="cursor: pointer; color: #409EFF;" 
                        onclick="handleFileDownload('${fileId}', '${escapedFileName}', false)">${fileName}</span>`
                    }
                  </div>
                `;
              });
            }
            formattedContent += '</div>';

            window.handleFileDownload = async (fileId: string, fileName: string, isFolder: boolean) => {
              try {
                if (isFolder) { ElMessage.warning('文件夹不支持下载'); return; }
                const response = await downloadUrlParam({ fileIds: [fileId] });
                if (response.data && response.data.success) {
                  response.data.data.forEach((info: any) => {
                    fetch(info.downloadUrl).then(r => r.blob()).then(blob => {
                      const link = document.createElement('a');
                      link.href = URL.createObjectURL(blob);
                      link.download = info.fileName;
                      document.body.appendChild(link);
                      link.click();
                      URL.revokeObjectURL(link.href);
                      document.body.removeChild(link);
                    });
                  });
                  ElMessage.success('开始下载文件');
                } else ElMessage.error(response.data?.msg || '获取下载链接失败');
              } catch (error) {
                console.error('下载错误:', error);
                ElMessage.error('下载文件失败');
              }
            };
          } 
          else if (responseData.data && responseData.data.type === 'file_statistics') {
            const stats = responseData.data.data;
            const fileTypeMap: { [key: string]: { icon: string; name: string } } = {
              IMG: { icon: '🖼️', name: '图片' },
              DOC: { icon: '📄', name: '文档' },
              VIDEO: { icon: '🎥', name: '视频' },
              AUDIO: { icon: '🎵', name: '音频' },
              PDF: { icon: '📑', name: 'PDF' },
              other: { icon: '📁', name: '其他' }
            };

            let typeStatsHtml = '';
            if (stats?.file_types) {
              Object.entries(stats.file_types).forEach(([type, count]) => {
                const typeInfo = fileTypeMap[type] || { icon: '📁', name: type };
                typeStatsHtml += `
                  <div class="file-type-item">
                    <span class="type-icon">${typeInfo.icon}</span>
                    <div class="type-info"><span class="type-name">${typeInfo.name}</span><span class="type-count">${count} 个文件</span></div>
                  </div>
                `;
              });
            }

            formattedContent = `
              <div class="file-statistics animate-fade-in-up">
                <div class="stats-header">
                  <div class="total-files">
                    <span class="total-number">${stats.total_files || 0}</span>
                    <span class="total-label">总文件数</span>
                  </div>
                </div>
                ${typeStatsHtml || '<div class="empty-stats">未获取到文件统计数据</div>'}
              </div>
            `;
          } 
          else formattedContent = '未识别的响应类型，请尝试重新查询';
        } else formattedContent = `查询失败：${responseData.msg || '服务器未返回错误信息'}`;

        const lastMsgIndex = messages.value.length - 1;
        messages.value[lastMsgIndex] = { isUser: false, content: formattedContent, isLoading: false };
      } catch (error) {
        console.error('查询出错:', error);
        const errorMsg = error instanceof Error ? error.message : '未知错误';
        const lastMsgIndex = messages.value.length - 1;
        messages.value[lastMsgIndex] = {
          isUser: false,
          content: `抱歉，查询过程中发生错误：${errorMsg}，请稍后重试`,
          isLoading: false
        };
        ElMessage.error(`查询失败：${errorMsg}`);
      } finally {
        isLoading.value = false;
        scrollToBottom();
      }
    };

    return {
      messages, inputMessage, messageList, sendMessage, userAvatar,
      assistantAvatar, isLoading, inputFocused
    };
  }
});
</script>

<style scoped>
/* 合并为紧凑CSS格式 */
.chat-container{display:flex;flex-direction:column;height:100vh;background:#f8fafc;}
.message-list{flex:1;overflow-y:auto;padding:20px;display:flex;flex-direction:column;gap:16px;}
.message-item{display:flex;gap:12px;max-width:80%;}
.message-item.user-message{margin-left:auto;flex-direction:row-reverse;}
.message-item.user-message .message-content{background:#e6f7ff;color:#001529;}
.message-item.assistant-message{margin-right:auto;}
.message-item.assistant-message .message-content{background:#fff;color:#001529;}
.avatar{width:40px;height:40px;border-radius:50%;overflow:hidden;flex-shrink:0;box-shadow:0 2px 6px rgba(0,0,0,0.1);}
.avatar-img{width:100%;height:100%;object-fit:cover;transition:transform 0.3s ease;}
.avatar-img:hover{transform:scale(1.05);}
.message-content{padding:12px 16px;border-radius:12px;font-size:14px;line-height:1.6;word-break:break-word;min-height:24px;box-shadow:0 2px 8px rgba(0,0,0,0.05);}
.loading-indicator{display:flex;align-items:center;justify-content:center;height:40px;}
.loading-container{display:flex;flex-direction:column;align-items:center;gap:8px;padding:16px 0;}
.loading-tip{font-size:13px;color:#64748b;text-align:center;line-height:1.5;}
.input-area{padding:16px 20px;background:#fff;border-top:1px solid #e2e8f0;}
.input-wrapper{position:relative;max-width:1080px;min-height:60px;margin:0 auto;background:#fff;border-radius:24px;border:2px solid #e2e8f0;padding:14px 60px 14px 20px;transition:all 0.2s;}
.input-wrapper:focus-within{border-color:#409eff;box-shadow:0 0 0 3px rgba(64,158,255,0.1);}
.message-input{width:100%;border:none;background:transparent;resize:none;outline:none;font-size:14px;line-height:1.5;max-height:180px;overflow-y:auto;}
.input-focused .input-wrapper{border-color:#409eff;box-shadow:0 0 0 3px rgba(64,158,255,0.1);}
.input-disabled{opacity:0.6;cursor:not-allowed;}
.send-button{position:absolute;right:12px;bottom:12px;width:36px;height:36px;display:flex;align-items:center;justify-content:center;cursor:pointer;border-radius:50%;transition:all 0.3s;}
.send-button svg{fill:#94a3b8;transition:all 0.3s;}
.send-button.active svg{fill:#409eff;}
.send-button:hover{background:rgba(64,158,255,0.1);}
.send-button.active:hover{background:rgba(64,158,255,0.2);}
.send-button.disabled{cursor:not-allowed;background:transparent !important;}
.send-button.disabled svg{fill:#cbd5e1 !important;}
.send-loading{display:flex;align-items:center;justify-content:center;}
::-webkit-scrollbar{width:6px;height:6px;}
::-webkit-scrollbar-track{background:#f1f5f9;border-radius:3px;}
::-webkit-scrollbar-thumb{background:#cbd5e1;border-radius:3px;}
::-webkit-scrollbar-thumb:hover{background:#94a3b8;}

/* 穿透scoped样式，作用于v-html生成的文件列表 */
:deep(.file-list) {
  display:flex;flex-direction:column;gap:8px;padding:10px;background:#fff;border-radius:8px;
}
:deep(.file-item) {
  display:flex;align-items:center;padding:8px;border-radius:4px;background:#f5f7fa;transition:all 0.3s;
}
:deep(.file-item:hover) {
  background:#e6f7ff;transform:translateX(4px);
}
:deep(.file-icon) {
  font-size:20px;margin-right:12px;
}
:deep(.file-name) {
  flex:1;margin-right:16px;color:#303133;
}
:deep(.empty-file-list) {
  padding:16px;text-align:center;color:#94a3b8;font-size:13px;background:#f8fafc;border-radius:4px;margin-top:8px;
}

.storage-info{background:#fff;border-radius:8px;padding:20px;box-shadow:0 2px 12px rgba(0,0,0,0.1);}
.storage-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px;}
.storage-title{font-size:16px;font-weight:500;color:#303133;}
.storage-percentage{font-size:20px;font-weight:600;color:#409EFF;}
.storage-progress{height:8px;background:#E6E8EB;border-radius:4px;overflow:hidden;margin-bottom:16px;}
.progress-bar{height:100%;background:linear-gradient(90deg,#409EFF 0%,#36D1DC 100%);border-radius:4px;transition:width 0.5s ease;}
.storage-details{display:flex;justify-content:space-between;}
.storage-used,.storage-total{display:flex;flex-direction:column;gap:4px;}
.label{font-size:14px;color:#909399;}
.value{font-size:16px;font-weight:500;color:#303133;}
.file-statistics{background:#fff;border-radius:12px;padding:24px;box-shadow:0 2px 12px rgba(0,0,0,0.1);}
.stats-header{margin-bottom:20px;}
.total-files{text-align:center;}
.total-number{font-size:36px;font-weight:600;color:#409EFF;display:block;}
.total-label{font-size:14px;color:#909399;margin-top:4px;}
:deep(.file-type-item) {
  display:flex;align-items:center;padding:12px;background:#F5F7FA;border-radius:8px;transition:all 0.3s;
}
:deep(.file-type-item:hover) {
  background:#ECF5FF;transform:translateY(-2px);
}
:deep(.type-icon) {
  font-size:24px;margin-right:12px;
}
:deep(.type-info) {
  display:flex;flex-direction:column;
}
:deep(.type-name) {
  font-size:14px;font-weight:500;color:#303133;
}
:deep(.type-count) {
  font-size:12px;color:#909399;margin-top:2px;
}
:deep(.empty-stats) {
  padding:16px;text-align:center;color:#94a3b8;font-size:13px;background:#f8fafc;border-radius:4px;margin-top:8px;
}
.animate-fade-in{animation:fadeIn 0.4s ease forwards;opacity:0;}
.animate-fade-in-up{animation:fadeInUp 0.5s ease forwards;opacity:0;transform:translateY(10px);}
@keyframes fadeIn{from{opacity:0;}to{opacity:1;}}
@keyframes fadeInUp{from{opacity:0;transform:translateY(10px);}to{opacity:1;transform:translateY(0);}}
@media (max-width:968px){
  .message-list{padding:16px;gap:12px;}
  .message-item{max-width:85%;}
  .input-area{padding:12px 16px;}
  .input-wrapper{padding:12px 56px 12px 16px;}
  .storage-info{padding:16px;}
  .file-statistics{padding:20px;}
  .loading-tip{font-size:12px;}
}
@media (max-width:576px){
  .message-list{padding:12px;gap:10px;}
  .message-item{max-width:90%;}
  .avatar{width:36px;height:36px;}
  .message-content{padding:10px 14px;font-size:13px;border-radius:8px;}
  .input-area{padding:10px 12px;}
  .input-wrapper{min-height:50px;border-radius:20px;padding:10px 50px 10px 14px;}
  .message-input{font-size:13px;}
  .send-button{width:32px;height:32px;}
  .send-button svg{width:20px;height:20px;}
  .storage-header{margin-bottom:12px;}
  .storage-title{font-size:14px;}
  .storage-percentage{font-size:18px;}
  .total-number{font-size:30px;}
  .file-item{padding:6px;}
  .file-icon{font-size:18px;}
  .loading-tip{font-size:11px;}
}
</style>
